package com.onpositive.dataminer.rcp.views;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.viewers.IStructuredSelection;

import com.onpositive.dataminer.core.AuditManager;
import com.onpositive.dataminer.core.AuditManager.ObjEntry;
import com.onpositive.dataminer.core.DefaultUniverse;
import com.onpositive.knowledge.model.IThing;
import com.onpositive.knowledge.model.impl.MergingProperty;
import com.onpositive.knowledge.model.value.audits.AbstractAuditResult;
import com.onpositive.knowledge.model.values.DescribedValue;
import com.onpositive.knowledge.model.values.IHasValue;
import com.onpositive.knowledge.model.values.IValueTransformer;
import com.onpositive.knowledge.model.values.PropertyValuePair;
import com.onpositive.semantic.model.api.changes.IValueListener;
import com.onpositive.semantic.model.api.expressions.IListenableExpression;
import com.onpositive.semantic.model.api.property.IProperty;
import com.onpositive.semantic.model.api.property.PropertyAccess;
import com.onpositive.semantic.model.api.realm.CollectionBasedRealm;
import com.onpositive.semantic.model.api.realm.IRealm;
import com.onpositive.semantic.model.api.realm.Realm;
import com.onpositive.semantic.model.binding.Binding;
import com.onpositive.semantic.model.ui.property.editors.structured.ListEnumeratedValueSelector;
import com.onpositive.semantic.ui.workbench.elements.SelectionBinding;
import com.onpositive.semantic.ui.workbench.elements.XMLView;
import com.onpositive.units.ParsedDimension;
import com.onpositive.units.ParsedString;
import com.onpositive.units.ParsedValue;
import com.onpositive.units.ParsedValueSequenceV2;

public class PropertyValuesView extends XMLView {

	private SelectionBinding m;

	public PropertyValuesView() {
		super("/ui/valueList.dlf");
//		setSelectionProvider("valTab");
	}

	@Override
	public void dispose() {
		m.dispose();
		super.dispose();
	}

	public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
		
		m = new SelectionBinding(getViewSite()) {
			
			private static final long serialVersionUID = -103862036018932142L;

			public void setValue(Object value) {
				
				if( value == null )
					return ;
				
				if ( value instanceof IProperty ) {
					super.setValue(value);
					selectedProp = (IProperty) value ;
					return ;
				}				
				
//				if ( value instanceof IThing ){
//					selectedThing =  (IThing) value ;
//					return ;
//				}
				
					if ( value instanceof AuditManager.ObjEntry<?> ){
					final ObjEntry<?> objEntry = (AuditManager.ObjEntry<?>)value;
					Object obj = objEntry.getObject() ;
					if( !(obj instanceof IValueTransformer) )
						return ;
					
					selectedTransformerId = objEntry.getId() ;
					Binding bnd = PropertyValuesView.this.getBinding("transformerId");
					bnd.setValue(selectedTransformerId) ;
					return ;
				}
			};
		};
		m.setId("selection");
		getBinding().addChild(m);
		DefaultUniverse.getInstance().getAuditManager().addValueListener( new IValueListener<Object>() {

			private static final long serialVersionUID = 1L;

			@Override
			public void valueChanged(Object oldValue, Object newValue) {
				Binding binding = (Binding) getBinding().getBinding("cleanMode");
				Object value = binding.getValue();
				if(value instanceof Boolean){
					boolean b = (Boolean) value;
					binding.setValue(!b);
					binding.setValue(b);
				}
			}
		});
		super.createPartControl(parent);
	};

	IRealm<PropertyValuePair> getAllObjects(IProperty prop,Boolean merge) {
		
		if(prop==null)
			return null;
		
		IRealm<IThing> all = DefaultUniverse.getInstance().all();
		
		ArrayList<PropertyValuePair> list = new ArrayList<PropertyValuePair>(); 
		for(IThing obj : all){
			Object val = null;
			if(merge){		
				AbstractAuditResult auditResult = DefaultUniverse.getInstance().getAuditResult();		
				MergingProperty mProp = new MergingProperty(prop, auditResult);
				
				val = mProp.getValue(obj);
				
				if(val instanceof ParsedValue) {
					ParsedValue converted = ParsedDimension.convertDimensions((ParsedValue) val);
					if(converted!=null)
						val = converted;
				}
					
				if(val instanceof String)
					val = new ParsedString((String)val, "");
			}
			else{
				val = prop.getValue(obj);
			}
			String comment = (String) ((val instanceof IHasValue) ? ((IHasValue)val).getComment() : "");
			PropertyValuePair pair = new PropertyValuePair(prop, new DescribedValue(val,comment), obj, comment);
			list.add(pair);
		}		
		return new Realm<PropertyValuePair>(list);
	}
	
	private IProperty selectedProp = null ;
	private String selectedTransformerId = null ;
	
	public void addInspectionValues()
	{
		if( selectedProp == null || selectedTransformerId == null )
			return ;
		
		Binding binding = getBinding("selBnd") ;
		Object obj = binding.getValue() ;
		if( !(obj instanceof IThing) )
			return ;
		
		IThing selectedThing = (IThing) obj ;
		
		AuditManager auditManager = (AuditManager) DefaultUniverse.getInstance().getAuditManager();
		auditManager.addInspectionValue(selectedThing, selectedProp, selectedTransformerId ) ;		
	}
	
	public void depricate(){
		IStructuredSelection sel = ((ListEnumeratedValueSelector<?>)getElement("valTab")).getSelection();
		Object[] array = sel.toArray();
		for( Object o:array){
			PropertyAccess.setValue("Depricated",o, true);
		}
	}
	
	public Object computeValue(Object obj, IProperty prop, Boolean merge){
		
		if(prop==null||obj==null)
			return null;
		
		Object val = null;
		if(merge){		
			AbstractAuditResult auditResult = DefaultUniverse.getInstance().getAuditResult();		
			MergingProperty mProp = new MergingProperty(prop, auditResult);
			
			val = mProp.getValue(obj);
			
			if(val instanceof ParsedValue) {
				ParsedValue converted = ParsedDimension.convertDimensions((ParsedValue) val);
				if(converted!=null)
					val = converted;
			}
				
			if(val instanceof String)
				val = new ParsedString((String)val, "");
		}
		else{
			val = prop.getValue(obj);
		}
		String comment = (String) ((val instanceof IHasValue) ? ((IHasValue)val).getComment() : "");
		PropertyValuePair pair = new PropertyValuePair(prop, new DescribedValue(val,comment), obj, comment);
		return pair;
	}
	
	

	public Object getValuesForGrouping(Object obj, IProperty prop){
		
		if(obj instanceof PropertyValuePair)
			obj=((PropertyValuePair)obj).getTarget();
		
		if(prop==null||obj==null)
			return null;
		
		Object value = prop.getValue(obj);
		if(value==null)
			return "Empty";
		
		if(!(value instanceof DescribedValue))
			return value;
		
		ArrayList<Object> list = toList(value,null);
		return list;
	}

	@SuppressWarnings("rawtypes")
	private ArrayList<Object> toList(Object value,ArrayList<Object> list) {
		
		if(value == null)
			return null;
		
		if(list==null)
			list = new ArrayList<Object>();

		if(value instanceof DescribedValue){
			DescribedValue dv = (DescribedValue) value;
			Object value1 = dv.value();
			toList(value1, list);
		}
		else if(value instanceof Iterable){
			Iterable iterable = (Iterable) value;
			for(Object o : iterable){
				toList(o, list);
			}
		}
		else if(value.getClass().isArray()){
			Object[] arr = (Object[]) value;
			for(Object o : arr){
				toList(o, list);
			}
		}
		else if(value instanceof ParsedValueSequenceV2){
			ParsedValueSequenceV2 pvs = (ParsedValueSequenceV2) value;
			ParsedValue[] vArr = pvs.getValuesArray();			
			toList(vArr, list);
		}
		else{
			list.add(value);
		}
		
		return list;
	}
}
